---
title: "OAuth2认证方式"
date: 2018-06-01
categories:
- rfc
tags:
---

<div id="content">
<div id="table-of-contents">
<h2>Table of Contents</h2>
<div id="text-table-of-contents">
<ul>
<li><a href="#orge5fcd6b">Intro</a></li>
<li><a href="#org07fa2e3">Authorization Code</a>
<ul>
<li><a href="#orge3160c0">Authorization Request</a></li>
<li><a href="#org9243c48">Authorization Response</a></li>
<li><a href="#orge8f30c5">Token Request</a></li>
<li><a href="#org2bebe89">Token Response</a></li>
</ul>
</li>
<li><a href="#org0aae793">Implicit</a></li>
<li><a href="#org9cb02fc">Resource Owner Password Credentials</a></li>
<li><a href="#org53147a9">Client Credentials</a>
<ul>
<li><a href="#orgc0c2073">Request</a></li>
<li><a href="#org06bb373">Response</a></li>
</ul>
</li>
</ul>
</div>
</div>
<blockquote>
<p>
<a href="https://www.rfc-editor.org/rfc/rfc6749.txt">https://www.rfc-editor.org/rfc/rfc6749.txt</a>
</p>
</blockquote>
<div class="outline-2" id="outline-container-orge5fcd6b">
<h2 id="orge5fcd6b">Intro</h2>
<div class="outline-text-2" id="text-orge5fcd6b">
<p>
在下面中提到的“客户程序”，不是指的用户终端。
</p>
<p>
在客户程序请求资源服务器上资源之前，客户程序需要先在资源服务器关联的授权服务器上注册。
注册之后，授权服务给客户程序一个ClientID和ClientSecret。
ClientId在授权服务器上是唯一的。
ClientSecret就是Secret的。
注册的时候，客户程序还需要提交一个Redirect URI，用于授权成功之后的重定向。
</p>
<p>
OAuth 2.0标准包含了四种授权方式
</p>
</div>
</div>
<div class="outline-2" id="outline-container-org07fa2e3">
<h2 id="org07fa2e3">Authorization Code</h2>
<div class="outline-text-2" id="text-org07fa2e3">
<div class="figure">
<p><img alt="authorization-code-seq.png" src=".oauth/authorization-code-seq.png"/>
</p>
</div>
<ol class="org-ol">
<li>资源所有者（用户）请求客户程序</li>
<li>客户程序告诉用户通过授权服务（例如Facebook Twitter, Google）来登录</li>
<li>为了让用户去授权服务登录，客户程序将用户重定向到授权服务器。重定向的同时，客户程序也将自己的ClientID发送块过去。</li>
<li>用户在授权服务中登录。成功之后，询问用户是否要将赋予客户程序访问自己的资源的权限。</li>
</ol>
<p>
如果用户选择确定，则用户被重定向至客户程序，重定向的地址就是客户程序向授权服务注册时提交的地址。
如果用户已经登录了授权服务（例如先前登录了，然后选择了“保持登录”），则用户直接被询问是否授权。
</p>
<ol class="org-ol">
<li>重定向到客户程序的时候，授权服务向客户程序发送了一个授权码。</li>
<li>客户程序向授权服务发起请求，将自己的ClientID和ClientSecret和授权码一起发送</li>
<li>授权服务验证之后，返回Access Token</li>
<li>客户程序现在能通过Access Token访问资源服务器了。</li>
</ol>
</div>
<div class="outline-3" id="outline-container-orge3160c0">
<h3 id="orge3160c0">Authorization Request</h3>
<div class="outline-text-3" id="text-orge3160c0">
<table border="2" cellpadding="6" cellspacing="0" frame="hsides" rules="groups">
<colgroup>
<col class="org-left"/>
<col class="org-left"/>
<col class="org-left"/>
</colgroup>
<thead>
<tr>
<th class="org-left" scope="col">Request Parameter</th>
<th class="org-left" scope="col">Value</th>
<th class="org-left" scope="col">Note</th>
</tr>
</thead>
<tbody>
<tr>
<td class="org-left">response_type</td>
<td class="org-left">code</td>
<td class="org-left">org-export-with-sub-superscripts)</td>
</tr>
<tr>
<td class="org-left">client_id</td>
<td class="org-left"> </td>
<td class="org-left">Required</td>
</tr>
<tr>
<td class="org-left">redirect_uri</td>
<td class="org-left"> </td>
<td class="org-left">Optional，注册时提交的重定向地址</td>
</tr>
<tr>
<td class="org-left">scope</td>
<td class="org-left"> </td>
<td class="org-left">Optional</td>
</tr>
<tr>
<td class="org-left">state</td>
<td class="org-left"> </td>
<td class="org-left">Optional but recommended,</td>
</tr>
</tbody>
</table>
</div>
</div>
<div class="outline-3" id="outline-container-org9243c48">
<h3 id="org9243c48">Authorization Response</h3>
<div class="outline-text-3" id="text-org9243c48">
<table border="2" cellpadding="6" cellspacing="0" frame="hsides" rules="groups">
<colgroup>
<col class="org-left"/>
<col class="org-left"/>
</colgroup>
<thead>
<tr>
<th class="org-left" scope="col">Response Field</th>
<th class="org-left" scope="col">Note</th>
</tr>
</thead>
<tbody>
<tr>
<td class="org-left">code</td>
<td class="org-left">Required</td>
</tr>
<tr>
<td class="org-left">state</td>
<td class="org-left">Required，如果请求中传递了这个参数，返回的值与传递的值相同</td>
</tr>
</tbody>
</table>
</div>
</div>
<div class="outline-3" id="outline-container-orge8f30c5">
<h3 id="orge8f30c5">Token Request</h3>
<div class="outline-text-3" id="text-orge8f30c5">
<table border="2" cellpadding="6" cellspacing="0" frame="hsides" rules="groups">
<colgroup>
<col class="org-left"/>
<col class="org-left"/>
<col class="org-left"/>
</colgroup>
<thead>
<tr>
<th class="org-left" scope="col">Request Parameters</th>
<th class="org-left" scope="col">Value</th>
<th class="org-left" scope="col">Note</th>
</tr>
</thead>
<tbody>
<tr>
<td class="org-left">client_id</td>
<td class="org-left"> </td>
<td class="org-left">Required</td>
</tr>
<tr>
<td class="org-left">client_secret</td>
<td class="org-left"> </td>
<td class="org-left">Required</td>
</tr>
<tr>
<td class="org-left">grant_type</td>
<td class="org-left">authorization_code</td>
<td class="org-left">Must be “authorization_code"</td>
</tr>
<tr>
<td class="org-left">code</td>
<td class="org-left"> </td>
<td class="org-left">Required</td>
</tr>
<tr>
<td class="org-left">redirect_uri</td>
<td class="org-left"> </td>
<td class="org-left">如果authorization request中包含了这个参数，则这里也必须</td>
</tr>
</tbody>
</table>
</div>
</div>
<div class="outline-3" id="outline-container-org2bebe89">
<h3 id="org2bebe89">Token Response</h3>
<div class="outline-text-3" id="text-org2bebe89">
<table border="2" cellpadding="6" cellspacing="0" frame="hsides" rules="groups">
<colgroup>
<col class="org-left"/>
<col class="org-left"/>
</colgroup>
<thead>
<tr>
<th class="org-left" scope="col">Response Field</th>
<th class="org-left" scope="col">Note</th>
</tr>
</thead>
<tbody>
<tr>
<td class="org-left">access_token</td>
<td class="org-left"> </td>
</tr>
<tr>
<td class="org-left">token_type</td>
<td class="org-left"> </td>
</tr>
<tr>
<td class="org-left">expires_in</td>
<td class="org-left">Optional, 过期时间</td>
</tr>
<tr>
<td class="org-left">refresh_token</td>
<td class="org-left">这个token过期之后，使用refresh_token获取新的</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
<div class="outline-2" id="outline-container-org0aae793">
<h2 id="org0aae793">Implicit</h2>
<div class="outline-text-2" id="text-org0aae793">
<div class="figure">
<p><img alt="implicit-seq.png" src=".oauth/implicit-seq.png"/>
</p>
</div>
<ol class="org-ol">
<li>用户请求客户程序</li>
<li>客户程序告诉用户去授权服务登录</li>
<li>用户前往授权服务，如果用户没有登录则先登录，然后选择是否授权</li>
<li>授权成功，重定向到Redirect URI，并将Accss Token直接附在url上，不是授权码了。</li>
<li>客户程序收到了Access Token，就能用来请求资源了。</li>
</ol>
<p>
这种方式的安全度就降低了。Access Token能够被用户代理（假如是个中了毒的浏览器）访问到。
并且ClientID和ClientSecret也要通过用户代理发送给授权服务器。
</p>
<p>
这种方式适用于内部程序的授权，或者本地应用程序。
</p>
</div>
</div>
<div class="outline-2" id="outline-container-org9cb02fc">
<h2 id="org9cb02fc">Resource Owner Password Credentials</h2>
<div class="outline-text-2" id="text-org9cb02fc">
<p>
用户将自己的（Twitter, Facebook等）的账号和密码提交给客户程序，然后客户程序使用该账号密码请求资源。
</p>
<p>
除非特别信任，一般人不会将自己的账号密码交给第三方保管。
</p>
</div>
</div>
<div class="outline-2" id="outline-container-org53147a9">
<h2 id="org53147a9">Client Credentials</h2>
<div class="outline-text-2" id="text-org53147a9">
<p>
这种方式适用于当客户程序需要调用资源服务器上的方法，面不是请求与用户相关的资源时。
</p>
</div>
<div class="outline-3" id="outline-container-orgc0c2073">
<h3 id="orgc0c2073">Request</h3>
<div class="outline-text-3" id="text-orgc0c2073">
<table border="2" cellpadding="6" cellspacing="0" frame="hsides" rules="groups">
<colgroup>
<col class="org-left"/>
<col class="org-left"/>
</colgroup>
<thead>
<tr>
<th class="org-left" scope="col">Request Parameter</th>
<th class="org-left" scope="col">Value</th>
</tr>
</thead>
<tbody>
<tr>
<td class="org-left">grant_type</td>
<td class="org-left">client_credentials</td>
</tr>
<tr>
<td class="org-left">scope</td>
<td class="org-left">Optional</td>
</tr>
</tbody>
</table>
<p>
除此之外，需要证明自己的身份，通过添加额外的 {% raw %} client_id {% endraw %} {% raw %} client_secret {% endraw %} 参数，或以 Basic的方式，将两个参数设置到请求头部。
例如：
</p>
<pre class="example">
POST /token HTTP/1.1
Host: authorization-server.com
 
grant_type=client_credentials
&amp;client_id=xxxxxxxxxx
&amp;client_secret=xxxxxxxxxx
</pre>
</div>
</div>
<div class="outline-3" id="outline-container-org06bb373">
<h3 id="org06bb373">Response</h3>
<div class="outline-text-3" id="text-org06bb373">
<table border="2" cellpadding="6" cellspacing="0" frame="hsides" rules="groups">
<colgroup>
<col class="org-left"/>
<col class="org-left"/>
</colgroup>
<thead>
<tr>
<th class="org-left" scope="col">Response Field</th>
<th class="org-left" scope="col">Note</th>
</tr>
</thead>
<tbody>
<tr>
<td class="org-left">access_token</td>
<td class="org-left"> </td>
</tr>
<tr>
<td class="org-left">token_type</td>
<td class="org-left"> </td>
</tr>
<tr>
<td class="org-left">expires_in</td>
<td class="org-left">过期时间， Optional</td>
</tr>
</tbody>
</table>
<p>
这种授权方式中不应该返回refresh token
</p>
</div>
</div>
</div>
</div>
<div class="status" id="postamble">
<p class="date">Date: 2018-06-01</p>
<p class="author">Author: gdme1320</p>
<p class="validation"><a href="http://validator.w3.org/check?uri=referer">Validate</a></p>
</div>
